package view.gui;

import java.awt.List;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;

import model.data.DataSource;
import model.data.Measurement;
import controler.algorithms.*;
import controler.algorithms.bayesian.gmm.GMMPredictor;
import controler.algorithms.ghsom.GHSOM;
import controler.algorithms.knn.KNN;
import controler.algorithms.nnbp.NNBP;
import controler.algorithms.timeseriesmodels.ARMAModel;
import controler.algorithms.timeseriesmodels.ARModel;
import controler.algorithms.timeseriesmodels.MAModel;
import controler.algorithms.timeseriesmodels.WMAModel;
import controler.metrics.*;
import controler.tools.*;
import controler.tools.excelexport.ExcelExporter;

/**
 * @mainpage Apliacja symulatora ruchu drogowego wraz elementami predykcji.
 * @author Piotr Stróżniak
 * @date 2011. 10. 13
 * @version 0.1
 * @brief Pierwsza wersja naszego systemu.
 */

/**
 * @file Application.java
 *
 **/

/**
 * @class Application
 * @brief Inicjalizacja aplikacji.
 * 
 * 
 **/

public class Init {

	/**
	 * @brief Metoda inicjująca aplikcję.
	 * 
	 */
	public static void main(String[] args) {

			Loader loader = new Loader();
			DataSource dataSource = null;
			
			String dataFile;
			int sizeOfTrainigSet;
			int count = 0;
			
			String name;
			
			int[] layersAndNeurons;
			double learningFactor;
			double momentum;
			double minError;
			int maxEpochs;
			int backSteps;
			long time;
			double lfCorrection;
			
			int KNN_h;
			int KNN_k;
			int KNN_metric;
			int KNN_mean;
			
			int H;
			int P;
			double rate;
			double tau1;
			double tau2;
			int x_size;
			int y_size;
			int cycles;
			
			int GMM_k;
			int MA_k;
			int WMA_k;
			int AR_p;
			int ARMA_p;
			int ARMA_q;
			
			LinkedList<Algorithm> algList = new LinkedList<Algorithm>();
			
			FileInputStream fstream;
			try {
				fstream = new FileInputStream("configuration.txt");
			
			  DataInputStream in = new DataInputStream(fstream);
			  BufferedReader br = new BufferedReader(new InputStreamReader(in));
			  String strLine;

			  while ((strLine = br.readLine()) != null)
			  {
				  if (count == 0)
				  {
					  try {
					  String[] parameters = strLine.split(";");
					  
					  dataFile = parameters[0];
					  sizeOfTrainigSet = Integer.parseInt(parameters[1]);
					  
					  loader.load(dataFile);
						
					  dataSource = loader.getDataSource();
					  
					  dataSource.divide(sizeOfTrainigSet);
					  
					  } catch (ArrayIndexOutOfBoundsException e) {
						  System.out.println("Blad linii.");
						  break;
					  } catch (NumberFormatException e) {
						  System.out.println("Zle parametry.");
						  break;
					  }
				  }
				  else
				  {
					  String[] parameters = strLine.split(";");
					  
					  if(parameters.length > 0)
					  {
						  if(parameters[0].equals("NNBP"))
						  {
							  try {
							  name = parameters[1];
							  int layers = Integer.parseInt(parameters[2]);
							  
							  layersAndNeurons = new int[layers];
							  
							  for(int i = 0 ; i < layers ; i++)
							  {
								  layersAndNeurons[i] = Integer.parseInt(parameters[3 + i]);
							  }
							  
							  learningFactor = Double.parseDouble(parameters[3 + layers]);
							  momentum = Double.parseDouble(parameters[4 + layers]);
							  minError = Double.parseDouble(parameters[5 + layers]);
							  maxEpochs = Integer.parseInt(parameters[6 + layers]);
							  backSteps = Integer.parseInt(parameters[7 + layers]);
							  time = Long.parseLong(parameters[8 + layers]);
							  lfCorrection = Double.parseDouble(parameters[9 + layers]);
							  
							  NNBP nnbp = new NNBP(name, layersAndNeurons, learningFactor, momentum, minError, maxEpochs, backSteps, time, lfCorrection);
							  
							  long timeStart = System.currentTimeMillis();
		                      nnbp.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      nnbp.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(nnbp);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("GHSOM"))
						  {
							  try {
							  name = parameters[1];
							  H = Integer.parseInt(parameters[2]);
							  P = Integer.parseInt(parameters[3]);
							  rate = Double.parseDouble(parameters[4]);
							  tau1 = Double.parseDouble(parameters[5]);
							  tau2 = Double.parseDouble(parameters[6]);
							  x_size = Integer.parseInt(parameters[7]);
							  y_size = Integer.parseInt(parameters[8]);
							  cycles = Integer.parseInt(parameters[9]);
							  
							  GHSOM ghsom = new GHSOM(H,P,rate,tau1,tau2,x_size,y_size,cycles);
							  ghsom.setModelName(name);
							  
							  GHSOM_LearnExtraction ge = new GHSOM_LearnExtraction(H,P);
		                      ghsom.setExtraction(ge);
		                      
		                      long timeStart = System.currentTimeMillis();
		                      ghsom.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      ghsom.setLearnigTime(timeEnd - timeStart);
		                      
		                      GHSOM_Extraction ghe = new GHSOM_Extraction(H,P);
		                      ghsom.setExtraction(ghe);
							  
							  algList.add(ghsom);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("KNN"))
						  {
							  try {
							  name = parameters[1];
							  KNN_h = Integer.parseInt(parameters[2]);
							  KNN_k = Integer.parseInt(parameters[3]);
							  KNN_mean = Integer.parseInt(parameters[4]);
							  KNN_metric = Integer.parseInt(parameters[5]);
							  
							  KNN knn = new KNN(KNN_k, KNN_h, KNN_mean, KNN_metric);
							  knn.setModelName(name);
							  
							  long timeStart = System.currentTimeMillis();
		                      knn.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      knn.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(knn);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("GMM"))
						  {
							  try {
							  name = parameters[1];
							  GMM_k = Integer.parseInt(parameters[2]);
							  
							  GMMPredictor gmm = new GMMPredictor(GMM_k);
							  gmm.setModelName(name);
							  
							  long timeStart = System.currentTimeMillis();
		                      gmm.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      gmm.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(gmm);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("MA"))
						  {
							  try {
							  name = parameters[1];
							  MA_k = Integer.parseInt(parameters[2]);
							  
							  MAModel ma = new MAModel(MA_k);
							  ma.setModelName(name);
							  
							  long timeStart = System.currentTimeMillis();
		                      ma.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      ma.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(ma);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("WMA"))
						  {
							  try {
							  name = parameters[1];
							  WMA_k = Integer.parseInt(parameters[2]);
							  
							  WMAModel wma = new WMAModel(WMA_k);
							  wma.setModelName(name);
							  
							  long timeStart = System.currentTimeMillis();
		                      wma.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      wma.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(wma);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("AR"))
						  {
							  try {
							  name = parameters[1];
							  AR_p = Integer.parseInt(parameters[2]);
							  
							  ARModel ar = new ARModel(AR_p);
							  ar.setModelName(name);
							  
							  long timeStart = System.currentTimeMillis();
		                      ar.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      ar.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(ar);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
						  else if(parameters[0].equals("ARMA"))
						  {
							  try {
							  name = parameters[1];
							  ARMA_p = Integer.parseInt(parameters[2]);
							  ARMA_q = Integer.parseInt(parameters[3]);
							  
							  ARMAModel arma = new ARMAModel(ARMA_p, ARMA_q);
							  arma.setModelName(name);
							  
							  long timeStart = System.currentTimeMillis();
		                      arma.learnAlgorithm(dataSource.getTrainingSet().getList());
		                      long timeEnd = System.currentTimeMillis();
		                      arma.setLearnigTime(timeEnd - timeStart);
							  
							  algList.add(arma);
							  
							  } catch (ArrayIndexOutOfBoundsException e) {
								  System.out.println("Blad linii.");
							  }
						  }
					  }
					  else
					  {
						  System.out.println("Blad linii.");
					  }
				  }
				  count++;
			  }

			  in.close();
			} catch (FileNotFoundException e) {
				System.out.println("Brak pliku z konfiguracja!");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			if(algList.size() > 0)
			{
			
//				for(Algorithm alg: algList)
//				{
//					long timeStart = System.currentTimeMillis();
//					alg.learnAlgorithm(dataSource.getTrainingSet().getList());
//					long timeEnd = System.currentTimeMillis();
//					alg.setLearnigTime(timeEnd - timeStart);
//				}
			
				ExcelExporter exporter = new ExcelExporter("MA");
			
				for(int i = 0 ; i < algList.size() ; i++)
				{
					exporter.add(algList.get(i), algList.get(i).getModelName());
				}
			
				exporter.process(dataSource.getValidationSet());

				MetricCounter counter = new MetricCounter();
			
				for(int i = 0 ; i < algList.size() ; i++)
				{
					counter.add(algList.get(i), algList.get(i).getModelName());
				}

				counter.process(dataSource.getValidationSet());
			}
	}
}
